#include "ota_version.h"
#include "ota_http_curl.h"
#include <unistd.h>
#include "cJSON.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#include <sys/reboot.h>
#include "log.h"


char *get_file_sha(char *filepath) {
    FILE *file = fopen(filepath, "rb");
    if (!file) {
        perror("Failed to open file");
        return NULL;
    }

    unsigned char hash[SHA_DIGEST_LENGTH];
    SHA_CTX sha1;
    SHA1_Init(&sha1);

    const int bufSize = 32768;
    unsigned char *buffer = (unsigned char *)malloc(bufSize);
    if (!buffer) {
        perror("Failed to allocate memory");
        fclose(file);
        return NULL;
    }

    int bytesRead;
    while ((bytesRead = fread(buffer, 1, bufSize, file)) > 0) {
        SHA1_Update(&sha1, buffer, bytesRead);
    }

    SHA1_Final(hash, &sha1);
    fclose(file);
    free(buffer);

    char *outputBuffer = (char *)malloc(SHA_DIGEST_LENGTH * 2 + 1);
    if (!outputBuffer) {
        perror("Failed to allocate memory");
        return NULL;
    }

    for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
        sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
    }

    return outputBuffer;
}


/**
 * @brief 检查并更新程序
 * 1 网关程序 查询 远端ota服务发布的最新版本号
 *  1.1 http查询json 
 *  1.2 解析json 获取其中版本号
  2 和本地当前程序的版本号进行比对 如果本地低则需要下载远端应用程序
    
  3 下远端应用程序
  4 本地根据下载的文件生产一个验证码  (ai生成)
  5 和远端的验证码进行对比 如果相同则认可当前文件
  6 结束当前进程 
 */
 int  ota_check_update()
 {
	// * 1 网关程序 查询 远端ota服务发布的最新版本号
 // 1.1 http查询json 
    response_body_t *response_body= ota_http_curl_get_response(OTA_URL_FILEINFO);
	if(response_body==NULL)
	{	
		log_error("获取远端文件信息失败");
		return -1;
	}
	char *fileinfo_json= response_body->data;
	log_info("获取远端文件信息 %s",fileinfo_json);
 // 1.2 解析json 获取其中版本号
	 cJSON *root = cJSON_Parse(fileinfo_json);
	 if(root==NULL)
	 {
		 log_error("解析json失败");
		 return -1;
	 }
	 cJSON *version_major_json= cJSON_GetObjectItem(root,"major");
	 cJSON *version_minor_json= cJSON_GetObjectItem(root,"minor");
	 cJSON *version_patch_json= cJSON_GetObjectItem(root,"patch");
	 int version_major=version_major_json->valueint;
	 int version_minor=version_minor_json->valueint;
	 int version_patch=version_patch_json->valueint;
	 log_info("major:%d,minor:%d,patch:%d",version_major,version_minor,version_patch);

 // 2 和本地当前程序的版本号进行比对 如果本地低则需要下载远端应用程序
	if(VERSION_MAJOR>version_major  
		||(VERSION_MAJOR==version_major && VERSION_MINOR>version_minor )
		||(VERSION_MAJOR==version_major && VERSION_MINOR==version_minor && VERSION_PATCH>=version_patch)
	){
		log_info("未发现更高版本程序");
		return 0;
	}
	log_info("发现更高版本程序 %d.%d.%d :",version_major,version_minor,version_patch);
  //3 下远端应用程序
   unlink(OTA_LOCAL_FILE_PATH); //删除旧的本地文件
   int ret= ota_http_curl_download(OTA_URL_DOWNLOAD,OTA_LOCAL_FILE_PATH);
   if(ret!=0)
   {
	  log_error("下载失败");
	  return -1;
   }
   sleep(2);
  //4 本地根据下载的文件生产一个验证码  (ai生成)
	char *sha_local=get_file_sha(OTA_LOCAL_FILE_PATH);

  //5 和远端的验证码进行对比 如果相同则认可当前文件
	cJSON *sha1_ota_json= cJSON_GetObjectItem(root,"sha1");
	char *sha_ota=sha1_ota_json->valuestring;
	if(strcmp(sha_local,sha_ota)==0)
	{	
		log_info("下载成功,验证完成");
		free(response_body);
		free(sha_local);
		cJSON_Delete(root);
	}else
	{
		log_error("下载文件验证失败");
		free(response_body);
		free(sha_local);
		cJSON_Delete(root);
		unlink(OTA_LOCAL_FILE_PATH);
		return -1;
	}

  //6 结束当前进程 
	//重启系统 
	// reboot(RB_AUTOBOOT);

	return 0;

 }

  int  ota_check_update_daily()
  {
	while(1)
	{	sleep(24*60*60);
       ota_check_update ();
	   
	}
  }

   void ota_show_version()
   {
	 printf("当前版本号:%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH);
   }